package org.vison.wonfu.framework.codestyle.rules.impl;

import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
import org.vison.wonfu.framework.codestyle.config.CheckerConfig;
import org.vison.wonfu.framework.codestyle.issue.Issue;
import org.vison.wonfu.framework.codestyle.issue.IssueCollector;
import org.vison.wonfu.framework.codestyle.rules.CodeCheckRule;

import java.io.File;

/**
 * 类名检查规则：类名应使用大写开头的驼峰命名法
 */
public class ClassNameCheckRule implements CodeCheckRule {
    private static final String RULE_ID = "class-name-convention";
    private static final String RULE_NAME = "类名命名规范检查";
    private static final String RULE_DESCRIPTION = "检查类名是否符合大写开头的驼峰命名法";
    
    private boolean enabled = true;

    private boolean strict = false;
    
    @Override
    public String getId() {
        return RULE_ID;
    }
    
    @Override
    public String getName() {
        return RULE_NAME;
    }
    
    @Override
    public String getDescription() {
        return RULE_DESCRIPTION;
    }


    @Override
    public void initialize(CheckerConfig config) {
        this.enabled = config.isRuleEnabled(RULE_ID);
        this.strict = config.getRuleConfig(RULE_ID).isStrict();
    }

    @Override
    public boolean isStrict() {
        return strict;
    }
    
    @Override
    public void check(File file, CompilationUnit compilationUnit, IssueCollector collector) {
        if (!enabled) {
            return;
        }
        
        // 使用访问者模式检查所有类名
        compilationUnit.accept(new VoidVisitorAdapter<Void>() {
            @Override
            public void visit(ClassOrInterfaceDeclaration n, Void arg) {
                super.visit(n, arg);
                
                // 跳过接口检查
                if (n.isInterface()) {
                    return;
                }
                
                String className = n.getNameAsString();
                if (!Character.isUpperCase(className.charAt(0))) {
                    int lineNumber = n.getBegin().isPresent() ? n.getBegin().get().line : -1;
                    collector.addIssue(new Issue(
                            file,
                            lineNumber,
                            RULE_ID,
                            "类名 '" + className + "' 应以大写字母开头",
                            Issue.Severity.WARNING
                    ));
                }
            }
        }, null);
    }
}
